package com.example.design_pattern.proxy;

//net.sf.cglib.proxy.Enhancer 不是 JDK 自带的包，而是一个第三方库，它提供了CGLib动态代理的实现。
// CGLib（Code Generation Library）是一个开源的字节码生成库，它可以在运行时动态生成类的子类，并覆盖其中的方法来实现代理功能。
// 通常情况下，需要手动引入CGLib库，并将其添加到项目的依赖中，才能使用其中的功能。

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

// 这个包是java自带的
import java.lang.reflect.Method;

// 本案例演示的是cglib来做动态代理。
// 如果想要明白jdk动态代理和cglib动态代理的区别，必须要基于例子来看，如果单纯说的话，很难弄清楚。
public class ProxyTest04 {
    public static void main(String[] args) {
        // 创建一个Enhancer对象，用于生成代理类
        Enhancer enhancer = new Enhancer();
        // 设置被代理类的父类，也就是要被代理的类。在这里，RealSubject.class 是被代理类的类对象，表示要将RealSubject类作为被代理类。
        // 这里就体现了，cglib代理，是以被代理类为父类，然后通过它的一个子类，来代理它。
        enhancer.setSuperclass(RealSubject.class);
        // 不要觉得DynamicProxyInterceptor、DynamicProxyInterceptor implements MethodInterceptor、new DynamicProxyInterceptor()这三个东西很难理解，其实它们就是一种java里面设计代码常用的套路。
        // DynamicProxyInterceptor就是一个我们自己定义的类。类其实就是创建实例对象的模板，而实例对象，又是用来装状态(成员变量)和行为(方法)的。
        // DynamicProxyInterceptor implements MethodInterceptor这句，MethodInterceptor就是个接口而已。我们常说，接口就是制定规范和定义。它想规范一下DynamicProxyInterceptor这个自定义类，里面的方法一定要叫intercept，并且形参也实现按照后续调用时会传的设置好。后续就按照这个名字来专门调用这个方法的。
        // new DynamicProxyInterceptor(),本质上就是一个实例对象啊。上面我们说，实例对象就是装状态和行为的，行为就是方法。其实，我们就是想给enhancer添加一个叫做Callback的属性，这个属性的值，它是一个方法。后续直接enhancer.callback(),就可以调用intercept这个方法。
        enhancer.setCallback(new DynamicProxyInterceptor());
        // 这行代码是通过 enhancer.create() 方法创建一个代理对象，并将其强制转换为 RealSubject 类型的对象.
        // 这个代理对象就是通过 CGLib 动态代理生成的，可以代理 RealSubject 类中的方法调用。
        RealSubject proxySubject = (RealSubject) enhancer.create();
        proxySubject.doSomething();
    }
}

// 这个类就是一个装方法的一个包装纸而已。java中的体系决定了，写什么都很体系化、很严谨，看起来就觉得很古怪。各种类，各种接口之类的东西。
class DynamicProxyInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("DynamicProxyInterceptor is doing something before delegating...");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("DynamicProxyInterceptor is doing something after delegating...");
        return result;
    }
}

